🎖️GitЯра🎖️
Node / meshtastic / Meshtastic-Android / files / androidApp / src / google / kotlin / org / meshtastic / app / map / LocationHandler.kt
Displaying Raw • Download
androidApp/src/google/kotlin/org/meshtastic/app/map/LocationHandler.kt 01cd54907d62cd90913d3d071b6bc240cae365ef (01cd5490) Text, 6.63 KB
T8b949e/*
* Copyright (c) 2026 Meshtastic LLC
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
Tff7b72package T7ee787org.meshtastic.app.map
Tff7b72import T7ee787android.Manifest
Tff7b72import T7ee787android.app.Activity
Tff7b72import T7ee787android.content.ActivityNotFoundException
Tff7b72import T7ee787android.content.pm.PackageManager
Tff7b72import T7ee787androidx.activity.compose.rememberLauncherForActivityResult
Tff7b72import T7ee787androidx.activity.result.IntentSenderRequest
Tff7b72import T7ee787androidx.activity.result.contract.ActivityResultContracts
Tff7b72import T7ee787androidx.compose.runtime.Composable
Tff7b72import T7ee787androidx.compose.runtime.LaunchedEffect
Tff7b72import T7ee787androidx.compose.runtime.getValue
Tff7b72import T7ee787androidx.compose.runtime.mutableStateOf
Tff7b72import T7ee787androidx.compose.runtime.remember
Tff7b72import T7ee787androidx.compose.runtime.setValue
Tff7b72import T7ee787androidx.compose.ui.platform.LocalContext
Tff7b72import T7ee787androidx.core.content.ContextCompat
Tff7b72import T7ee787co.touchlab.kermit.Logger
Tff7b72import T7ee787com.google.android.gms.common.api.ResolvableApiException
Tff7b72import T7ee787com.google.android.gms.location.LocationRequest
Tff7b72import T7ee787com.google.android.gms.location.LocationServices
Tff7b72import T7ee787com.google.android.gms.location.LocationSettingsRequest
Tff7b72import T7ee787com.google.android.gms.location.Priority
Tff7b72private Tff7b72const Tff7b72val Te6edf3INTERVAL_MILLIS Tff7b72= T79c0ff1T79c0ff0T79c0ff0T79c0ff0T79c0ff0L
Tf0883e@SuppressTb4b4b4(Ta5d6ff"Ta5d6ffLongMethodTa5d6ff"Tb4b4b4)
Tf0883e@Composable
Tff7b72fun Td2a8ffLocationPermissionsHandlerTb4b4b4(Te6edf3onPermissionResultTb4b4b4: Tb4b4b4(Tffa657BooleanTb4b4b4) Tff7b72-Tff7b72> Tffa657UnitTb4b4b4) Tb4b4b4{
Tff7b72val Te6edf3context Tff7b72= Te6edf3LocalContextTb4b4b4.Te6edf3current
Tff7b72var Te6edf3localHasPermission Tff7b72by Te6edf3remember Tb4b4b4{
Te6edf3mutableStateOfTb4b4b4(
Te6edf3ContextCompatTb4b4b4.Te6edf3checkSelfPermissionTb4b4b4(Te6edf3contextTb4b4b4, Te6edf3ManifestTb4b4b4.Te6edf3permissionTb4b4b4.Te6edf3ACCESS_FINE_LOCATIONTb4b4b4) Tff7b72=Tff7b72=
Te6edf3PackageManagerTb4b4b4.Te6edf3PERMISSION_GRANTEDTb4b4b4,
Tb4b4b4)
Tb4b4b4}
Tff7b72val Te6edf3requestLocationPermissionLauncher Tff7b72=
Te6edf3rememberLauncherForActivityResultTb4b4b4(Te6edf3contract Tff7b72= Te6edf3ActivityResultContractsTb4b4b4.Te6edf3RequestPermissionTb4b4b4(Tb4b4b4)Tb4b4b4) Tb4b4b4{ Te6edf3isGranted Tff7b72-Tff7b72>
Te6edf3localHasPermission Tff7b72= Te6edf3isGranted
T8b949e// Defer to the LaunchedEffect(localHasPermission) to check settings before confirming via
T8b949e// onPermissionResult
T8b949e// if permission is granted. If not granted, immediately report false.
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3isGrantedTb4b4b4) Tb4b4b4{
Te6edf3onPermissionResultTb4b4b4(Tff7b72falseTb4b4b4)
Tb4b4b4}
Tb4b4b4}
Tff7b72val Te6edf3locationSettingsLauncher Tff7b72=
Te6edf3rememberLauncherForActivityResultTb4b4b4(Te6edf3contract Tff7b72= Te6edf3ActivityResultContractsTb4b4b4.Te6edf3StartIntentSenderForResultTb4b4b4(Tb4b4b4)Tb4b4b4) Tb4b4b4{ Te6edf3result Tff7b72-Tff7b72>
Tff7b72if Tb4b4b4(Te6edf3resultTb4b4b4.Te6edf3resultCode Tff7b72=Tff7b72= Te6edf3ActivityTb4b4b4.Te6edf3RESULT_OKTb4b4b4) Tb4b4b4{
Te6edf3LoggerTb4b4b4.Te6edf3d Tb4b4b4{ Ta5d6ff"Ta5d6ffLocation settings changed by user.Ta5d6ff" Tb4b4b4}
T8b949e// User has enabled location services or improved accuracy.
Te6edf3onPermissionResultTb4b4b4(Tff7b72trueTb4b4b4) T8b949e// Settings are now adequate, and permission was already granted.
Tb4b4b4} Tff7b72else Tb4b4b4{
Te6edf3LoggerTb4b4b4.Te6edf3d Tb4b4b4{ Ta5d6ff"Ta5d6ffLocation settings change cancelled by user.Ta5d6ff" Tb4b4b4}
T8b949e// User chose not to change settings. The permission itself is still granted,
T8b949e// but the experience might be degraded. For the purpose of enabling map features,
T8b949e// we consider this as success if the core permission is there.
T8b949e// If stricter handling is needed (e.g., block feature if settings not optimal),
T8b949e// this logic might change.
Te6edf3onPermissionResultTb4b4b4(Te6edf3localHasPermissionTb4b4b4)
Tb4b4b4}
Tb4b4b4}
Te6edf3LaunchedEffectTb4b4b4(Tffa657UnitTb4b4b4) Tb4b4b4{
T8b949e// Initial permission check
Tff7b72when Tb4b4b4(Te6edf3ContextCompatTb4b4b4.Te6edf3checkSelfPermissionTb4b4b4(Te6edf3contextTb4b4b4, Te6edf3ManifestTb4b4b4.Te6edf3permissionTb4b4b4.Te6edf3ACCESS_FINE_LOCATIONTb4b4b4)Tb4b4b4) Tb4b4b4{
Te6edf3PackageManagerTb4b4b4.Te6edf3PERMISSION_GRANTED Tff7b72-Tff7b72> Tb4b4b4{
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3localHasPermissionTb4b4b4) Tb4b4b4{
Te6edf3localHasPermission Tff7b72= Tff7b72true
Tb4b4b4}
T8b949e// If permission is already granted, proceed to check location settings.
T8b949e// The LaunchedEffect(localHasPermission) will handle this.
T8b949e// No need to call onPermissionResult(true) here yet, let settings check complete.
Tb4b4b4}
Tff7b72else Tff7b72-Tff7b72> Tb4b4b4{
T8b949e// Request permission if not granted. The launcher's callback will update localHasPermission.
Te6edf3requestLocationPermissionLauncherTb4b4b4.Te6edf3launchTb4b4b4(Te6edf3ManifestTb4b4b4.Te6edf3permissionTb4b4b4.Te6edf3ACCESS_FINE_LOCATIONTb4b4b4)
Tb4b4b4}
Tb4b4b4}
Tb4b4b4}
Te6edf3LaunchedEffectTb4b4b4(Te6edf3localHasPermissionTb4b4b4) Tb4b4b4{
T8b949e// Handles logic after permission status is known/updated
Tff7b72if Tb4b4b4(Te6edf3localHasPermissionTb4b4b4) Tb4b4b4{
T8b949e// Permission is granted, now check location settings
Tff7b72val Te6edf3locationRequest Tff7b72= Te6edf3LocationRequestTb4b4b4.Te6edf3BuilderTb4b4b4(Te6edf3PriorityTb4b4b4.Te6edf3PRIORITY_HIGH_ACCURACYTb4b4b4, Te6edf3INTERVAL_MILLISTb4b4b4)Tb4b4b4.Te6edf3buildTb4b4b4(Tb4b4b4)
Tff7b72val Te6edf3builder Tff7b72= Te6edf3LocationSettingsRequestTb4b4b4.Te6edf3BuilderTb4b4b4(Tb4b4b4)Tb4b4b4.Te6edf3addLocationRequestTb4b4b4(Te6edf3locationRequestTb4b4b4)
Tff7b72val Te6edf3client Tff7b72= Te6edf3LocationServicesTb4b4b4.Te6edf3getSettingsClientTb4b4b4(Te6edf3contextTb4b4b4)
Tff7b72val Te6edf3task Tff7b72= Te6edf3clientTb4b4b4.Te6edf3checkLocationSettingsTb4b4b4(Te6edf3builderTb4b4b4.Te6edf3buildTb4b4b4(Tb4b4b4)Tb4b4b4)
Te6edf3taskTb4b4b4.Te6edf3addOnSuccessListener Tb4b4b4{
Te6edf3LoggerTb4b4b4.Te6edf3d Tb4b4b4{ Ta5d6ff"Ta5d6ffLocation settings are satisfied.Ta5d6ff" Tb4b4b4}
Te6edf3onPermissionResultTb4b4b4(Tff7b72trueTb4b4b4) T8b949e// Permission granted and settings are good
Tb4b4b4}
Te6edf3taskTb4b4b4.Te6edf3addOnFailureListener Tb4b4b4{ Te6edf3exception Tff7b72-Tff7b72>
Tff7b72if Tb4b4b4(Te6edf3exception Tff7b72is Te6edf3ResolvableApiExceptionTb4b4b4) Tb4b4b4{
Tff7b72try Tb4b4b4{
Tff7b72val Te6edf3intentSenderRequest Tff7b72= Te6edf3IntentSenderRequestTb4b4b4.Te6edf3BuilderTb4b4b4(Te6edf3exceptionTb4b4b4.Te6edf3resolutionTb4b4b4)Tb4b4b4.Te6edf3buildTb4b4b4(Tb4b4b4)
Te6edf3locationSettingsLauncherTb4b4b4.Te6edf3launchTb4b4b4(Te6edf3intentSenderRequestTb4b4b4)
T8b949e// Result of this launch will be handled by locationSettingsLauncher's callback
Tb4b4b4} Tff7b72catch Tb4b4b4(Te6edf3sendExTb4b4b4: Te6edf3ActivityNotFoundExceptionTb4b4b4) Tb4b4b4{
Te6edf3LoggerTb4b4b4.Te6edf3d Tb4b4b4{ Ta5d6ff"Ta5d6ffError launching location settings resolution Tffd700${Te6edf3sendExTb4b4b4.Te6edf3messageTffd700}Ta5d6ff.Ta5d6ff" Tb4b4b4}
Te6edf3onPermissionResultTb4b4b4(Tff7b72trueTb4b4b4) T8b949e// Permission is granted, but settings dialog failed. Proceed.
Tb4b4b4}
Tb4b4b4} Tff7b72else Tb4b4b4{
Te6edf3LoggerTb4b4b4.Te6edf3d Tb4b4b4{ Ta5d6ff"Ta5d6ffLocation settings are not satisfiable.Tffd700${Te6edf3exceptionTb4b4b4.Te6edf3messageTffd700}Ta5d6ff" Tb4b4b4}
Te6edf3onPermissionResultTb4b4b4(Tff7b72trueTb4b4b4) T8b949e// Permission is granted, but settings not ideal. Proceed.
Tb4b4b4}
Tb4b4b4}
Tb4b4b4} Tff7b72else Tb4b4b4{
T8b949e// If permission is not granted, report false.
T8b949e// This case is primarily handled by the requestLocationPermissionLauncher's callback
T8b949e// if the initial state was denied, or if user denies it.
Te6edf3onPermissionResultTb4b4b4(Tff7b72falseTb4b4b4)
Tb4b4b4}
Tb4b4b4}
Tb4b4b4}
Served by rngit 1.5.0 - Generated in 0.06s